package edu.towson.cosc.cosc455.chad.markdowncompiler;
import edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer;

/**
 * 
 */

/**
 * @author cclark29
 *
 */
public class MySyntaxAnalyzer implements SyntaxAnalyzer {
	private MyLexicalAnalyzer lex;
	
	
	
	
	 public void addToken()
	 {
	  Compiler.temp.push(Compiler.token); 
	 }
	 
	    public void document() throws CompilerException {
	      lex.getNextToken();
	   
	            if(!Compiler.token.equalsIgnoreCase("#START DOCUMENT")){
	             String message = "A #START DOCUMENT annotation was expected when a " +
	                                    Compiler.token + " was found!";
	                throw new CompilerException(message);
	            }
	            else{
	             addToken();
	            }
	            
	            lex.getNextToken();
	            
	            if(Compiler.token.equalsIgnoreCase("#START DEFINE")){
	             while(Compiler.token.equalsIgnoreCase("#START DEFINE")){
	              define();
	              lex.getNextToken();
	             }
	         }
	         if(Compiler.token.equalsIgnoreCase("#START HEAD")){
	          head();
	          lex.getNextToken();
	         }
	         
	            body();
	            if(!Compiler.token.equalsIgnoreCase("#END DOCUMENT")){
	                String message = "A #END DOCUMENT annotation was expected when a " +
	                                    Compiler.token + " was found!";
	                throw new CompilerException(message);
	            }
	            else{
	             addToken();
	            }
	            if(Compiler.text.length() != 0){
	             String message = "There is unexpected temprmation found. " + 
	               "Please delete " + Compiler.text;
	             throw new CompilerException(message);
	            }
	    }
	   
	    public void body() throws CompilerException {
	     boolean endBody = false;
	     while(!endBody){
	      if(Compiler.token.equalsIgnoreCase("#START PARAGRAPH")){
	       paragraph();
	      }
	      else if(Compiler.token.equalsIgnoreCase("#START BOLD")){
	       bold();
	      }
	      else if(Compiler.token.equalsIgnoreCase("#START ITALICS")){
	       italics();        
	      }
	      else if(Compiler.token.equalsIgnoreCase("#START LIST")){
	       list();     
	      }
	      else if(Compiler.token.equalsIgnoreCase("#START USE")){
	       use();
	      }
	      else if(Compiler.token.equalsIgnoreCase("#NEWLINE")){
	       addToken();
	      }
	      else if(lex.check(Compiler.token)){
	       addToken();
	      }
	      else{
	       endBody = true;
	      }
	      if(!endBody){
	       lex.getNextToken();
	      }
	     }        
	}

	 public void head() throws CompilerException {
	  if(!Compiler.token.equalsIgnoreCase("#START HEAD")){
	         String message = "A #START HEAD annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	        else{
	         addToken();
	        }
	        
	        lex.getNextToken();
	        title();
	        
	        lex.getNextToken();
	        if(!Compiler.token.equalsIgnoreCase("#END HEAD")){
	            String message = "A #END HEAD annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	        else{
	         addToken();
	        }
	 }

	 public void title() throws CompilerException {
	        if(!Compiler.token.equalsIgnoreCase("#START TITLE")){
	         String message = "A #START TITLE annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	        else{
	         addToken();
	        }
	        
	        lex.getNextToken();
	        if(lex.check(Compiler.token)){

	         addToken();
	        }
	        
	        lex.getNextToken();
	        if(!Compiler.token.equalsIgnoreCase("#END TITLE")){
	            String message = "A #END TITLE annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	        else{
	         addToken();
	        }
	 }

	 public void paragraph() throws CompilerException {
	  if(!Compiler.token.equalsIgnoreCase("#START PARAGRAPH")){
	         String message = "A #START PARAGRAPH annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	  else{
	   addToken();
	  }
	  
	  lex.getNextToken();
	  while(!Compiler.token.equalsIgnoreCase("#END PARAGRAPH")){

	   if(Compiler.token.equalsIgnoreCase("#START PARAGRAPH")){
	    paragraph();
	   }

	   else if(Compiler.token.equalsIgnoreCase("#START DEFINE")){
	    define();
	   }

	   else if(Compiler.token.equalsIgnoreCase("#START USE")){
	    use();
	   }

	   else if(Compiler.token.equalsIgnoreCase("#START BOLD")){
	    bold();
	   }

	   else if(Compiler.token.equalsIgnoreCase("#START ITALICS")){
	    italics();
	   }

	   else if(Compiler.token.equalsIgnoreCase("#START LIST")){
	    list();
	   }

	   else if(Compiler.token.equalsIgnoreCase("#NEWLINE")){

	    addToken();
	   }
	   else if(lex.check(Compiler.token))
	   {
	    addToken();
	   }
	   else{

	    String message = "Tag is not applicable to this "
	      + "tag. ";
	    throw new CompilerException(message);
	   }
	   lex.getNextToken();
	  }
	        
	        if(!Compiler.token.equalsIgnoreCase("#END PARAGRAPH")){
	            String message = "A #END PARAGRAPH annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	        else{
	         addToken();
	     }
	 }

	 public void bold() throws CompilerException {
	  if(lex.isSpace(Compiler.token)){
	   addToken();
	   lex.getNextToken();
	  }
	  if(!Compiler.token.equalsIgnoreCase("#START BOLD")){
	         String message = "A #START BOLD annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	  else{
	   addToken();
	  }
	  
	  lex.getNextToken();
	  
	  while(!Compiler.token.equalsIgnoreCase("#END BOLD")){

	   if(Compiler.token.equalsIgnoreCase("#START DEFINE")){
	    define();
	   }

	   else if(Compiler.token.equalsIgnoreCase("#START USE")){
	    use();
	   }

	   else if(Compiler.token.equalsIgnoreCase("#START ITALICS")){
	    italics();
	   }

	   else if(Compiler.token.equalsIgnoreCase("#NEWLINE")){

	    addToken();
	   }
	   else if(lex.check(Compiler.token))
	   {
	    addToken();
	   }
	   else{

	    String message = "Tag is not applicable to this "
	      + "tag. ";
	    throw new CompilerException(message);
	   }
	   
	   lex.getNextToken();
	  }
	        
	        if(!Compiler.token.equalsIgnoreCase("#END BOLD")){
	            String message = "A #END BOLD annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	        else{
	         addToken();
	        }
	 }

	 public void italics() throws CompilerException {
	  if(!Compiler.token.equalsIgnoreCase("#START ITALICS")){
	         String message = "A #START ITALICS annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	  else{
	   addToken();
	  }
	  
	  lex.getNextToken();
	  
	  while(!Compiler.token.equalsIgnoreCase("#END ITALICS")){

	   if(Compiler.token.equalsIgnoreCase("#START DEFINE")){
	    define();
	   }

	   else if(Compiler.token.equalsIgnoreCase("#START USE")){
	    use();
	   }

	   else if(Compiler.token.equalsIgnoreCase("#NEWLINE")){

	    addToken();
	   }
	   else if(lex.check(Compiler.token))
	   {
	    addToken();
	   }
	   else{

	    String message = "Tag is not applicable to this "
	      + "tag. ";
	    throw new CompilerException(message);
	   }
	   lex.getNextToken();
	  }
	        
	        if(!Compiler.token.equalsIgnoreCase("#END ITALICS")){
	            String message = "A #END ITALICS annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	        else{
	         addToken();
	        }
	 }

	 public void list() throws CompilerException {
	  if(!Compiler.token.equalsIgnoreCase("#START LIST")){
	         String message = "A #START LIST annotation was expected when a " +
	                       Compiler.token + " was found!";
	         throw new CompilerException(message);
	     }
	  else{
	   addToken();
	  }
	         
	     lex.getNextToken();
	     while((!Compiler.token.equals("#END LIST")) && (!Compiler.text.isEmpty())){
	         item();
	         lex.getNextToken();
	     }

	     if(!Compiler.token.equalsIgnoreCase("#END LIST")){
	         String message = "A #END LIST annotation was expected when a " +
	                   Compiler.token + " was found!";
	         throw new CompilerException(message);
	     }
	     else{
	         addToken();
	     }
	 }

	 public void item() throws CompilerException {
	  if(!Compiler.token.equalsIgnoreCase("#START ITEM")){
	         String message = "A #START ITEM annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	  else{
	   addToken();
	  }
	  
	  lex.getNextToken();
	  while(!Compiler.token.equalsIgnoreCase("#END ITEM")){
	
	   if(Compiler.token.equalsIgnoreCase("#START LIST")){
	    list();
	   }
	   else if(Compiler.token.equalsIgnoreCase("#START DEFINE")){
	    define();
	   }
	   
	   else if(Compiler.token.equalsIgnoreCase("#START USE")){
	    use();
	   }
	   
	   else if(Compiler.token.equalsIgnoreCase("#NEWLINE")){

	    addToken();
	   }
	   else if(lex.check(Compiler.token)){
	    addToken();
	   }
	   else{

	    String message = "Tag is not applicable to this "
	      + "tag. ";
	    throw new CompilerException(message);
	   }
	   lex.getNextToken();
	  }
	  
	        if(!Compiler.token.equalsIgnoreCase("#END ITEM")){
	            String message = "A #END ITEM annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	        else{
	         addToken();
	        }
	 }

	 public void audio() throws CompilerException {
	   if(!Compiler.token.equalsIgnoreCase("#START AUDIO")){
	          String message = "A #START AUDIO annotation was expected when a " +
	                                 Compiler.token + " was found!";
	             throw new CompilerException(message);
	         }
	   else{
	    addToken();
	   }
	         
	   lex.getNextToken();
	   if(lex.check(Compiler.token))
	   {
	    addToken();
	    lex.getNextToken();
	   }
	   if(lex.isSpace(Compiler.token)){
	    addToken();
	    lex.getNextToken();
	   }
	      if(!Compiler.token.equalsIgnoreCase("#END AUDIO")){
	             String message = "A #END AUDIO annotation was expected when a " +
	                                 Compiler.token + " was found!";
	             throw new CompilerException(message);
	         }
	      else{
	       addToken();
	      }
	 }

	 public void video() throws CompilerException {
	   if(!Compiler.token.equalsIgnoreCase("#START VIDEO")){
	          String message = "A #START VIDEO annotation was expected when a " +
	                                 Compiler.token + " was found!";
	             throw new CompilerException(message);
	         }
	   else{
	    addToken();
	   }
	         
	   lex.getNextToken();
	   if(lex.check(Compiler.token))
	   {
	    addToken();
	    lex.getNextToken();
	   }
	   
	      if(!Compiler.token.equalsIgnoreCase("#END VIDEO")){
	             String message = "A #END VIDEO annotation was expected when a " +
	                                 Compiler.token + " was found!";
	             throw new CompilerException(message);
	      }
	      else{
	       addToken();
	      }
	 }

	 public void define() throws CompilerException {
	  if(!Compiler.token.equalsIgnoreCase("#START DEFINE")){
	         String message = "A #START DEFINE annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	  else{
	   addToken();
	  }
	        lex.getNextToken();
	        if(!Compiler.token.equalsIgnoreCase("#NAME")){
	         addToken();
	         String message = "A #NAME annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	        else{
	         addToken();
	        }
	        
	        lex.getNextToken(); 

	        if(lex.check(Compiler.token)){
	         addToken();
	        }
	        else{
	         String message = "The name of the object should be text only.";
	         throw new CompilerException(message);
	        }
	          
	        lex.getNextToken();
	        if(!Compiler.token.equalsIgnoreCase("#VALUE")){
	         String message = "A #VALUE annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	        else{
	         addToken();
	        }
	        
	        lex.getNextToken();
	        body();        
	        if(Compiler.token.equalsIgnoreCase("#START DEFINE")){
	         define();
	        }
	        if(!Compiler.token.equalsIgnoreCase("#END DEFINE")){
	            String message = "A #END DEFINE annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	        else{
	         addToken();
	        }
	 }

	 public void use() throws CompilerException {
	        if(!Compiler.token.equalsIgnoreCase("#START USE")){
	         String message = "A #START USE annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	        else{
	         addToken();
	        }
	        
	        lex.getNextToken();
	        if(lex.check(Compiler.token)){

	        addToken();
	        lex.getNextToken();
	        }
	        
	        if(!Compiler.token.equalsIgnoreCase("#END USE")){
	            String message = "A #END USE annotation was expected when a " +
	                                Compiler.token + " was found!";
	            throw new CompilerException(message);
	        }
	        else{
	         addToken();
	        }
	 }
	}